#pragma once
#include "mq_binding.hpp"
#include "mq_message.hpp"
#include "mq_exchange.hpp"
#include "mq_queue.hpp"

namespace xzt
{
    class VirtualHost
    {
    public:
        using ptr = std::shared_ptr<VirtualHost>;

    public:
        VirtualHost(const string &host_name, const std::string &basedir, const std::string &dbfile) : 
            _host_name(host_name),
            _p_em(std::make_shared<ExchangeManager>(dbfile)),
            _p_qm(std::make_shared<MsgQueueManager>(dbfile)),
            _p_bm(std::make_shared<BindingManager>(dbfile)),
            _p_mm(std::make_shared<MessageManager>(basedir))
        {
            // 获取所有队列信息，利用_p_mm通过队列名称恢复所有的历史消息数据
            QueueMap queues = _p_qm->allQueues();
            for (auto &q : queues)
            {
                DLOG("恢复队列【%s】的历史消息数据", q.first.c_str());
                _p_mm->initQueueMessage(q.first);
            }
        }

        // 交换机相关
        bool declareExchange(const std::string &name, const ExchangeType &type,
                             bool durable, bool auto_delete, const Exchange::args_mapType &args)
        {
            return _p_em->declareExchange(name, type, durable, auto_delete, args);
        }
        void deleteExchange(const std::string &name)
        {
            // 清除所有与该交换机绑定的队列的绑定关系，并删除交换机
            _p_bm->unbindExchange(name);
            _p_em->deleteExchange(name);
        }
        bool existsExchange(const std::string &name)
        {
            return _p_em->exists(name);
        }
        Exchange::ptr selectExchange(const std::string &name)
        {
            return _p_em->selectExchange(name);
        }

        // 队列相关
        bool declareMsgQueue(const std::string &name, bool exclusive, bool durable, bool auto_delete, const MsgQueue::args_mapType &args)
        {
            // 初始化队列消息管理器句柄，再声明队列
            _p_mm->initQueueMessage(name);
            DLOG("VirtualHost::declareMsgQueue: %s", name.c_str());
            return _p_qm->declareMsgQueue(name, exclusive, durable, auto_delete, args);
        }
        void deleteMsgQueue(const std::string &name)
        {
            // 删除队列中所有信息，清除所有与该队列绑定的交换机的绑定关系，并删除队列
            _p_mm->destroyQueueMessage(name);
            _p_bm->unbindMsgQueue(name);
            _p_qm->deleteMsgQueue(name);
        }
        bool existsMsgQueue(const std::string &name)
        {
            return _p_qm->exists(name);
        }
        QueueMap allQueues()
        {
            return _p_qm->allQueues();
        }

        // 绑定相关
        bool bind(const std::string &exchange_name, const std::string &msgqueue_name, const std::string &binding_key)
        {
            // 1.判断交换机是否存在
            Exchange::ptr p_exchange = _p_em->selectExchange(exchange_name);
            if (p_exchange == nullptr)
            {
                ELOG("交换机【%s】不存在", exchange_name.c_str());
                return false;
            }
            // 2.判断队列是否存在
            MsgQueue::ptr p_msgqueue = _p_qm->selectMsgQueue(msgqueue_name);
            if (p_msgqueue == nullptr)
            {
                ELOG("队列【%s】不存在", msgqueue_name.c_str());
                return false;
            }
            // 3.绑定 只有交换机和队列都是持久化的，消息进行持久化绑定才有意义
            bool is_durable = p_exchange->_durable && p_msgqueue->_durable;
            return _p_bm->bind(exchange_name, msgqueue_name, binding_key, is_durable);
        }
        bool unBind(const std::string &exchange_name, const std::string &msgqueue_name)
        {
            return _p_bm->unbind(exchange_name, msgqueue_name);
        }
        MsgQueueBindingMap getExchangeBindings(const std::string &exchange_name)
        {
            return _p_bm->getExchangeBindings(exchange_name);
        }
        bool existsBinding(const std::string &exchange_name, const std::string &msgqueue_name)
        {
            return _p_bm->exists(exchange_name, msgqueue_name);
        }

        // 消息相关
        bool basicPublish(const std::string &queue_name, const xzt::BasicPropeties *basic_props, const std::string &body)
        {
            MsgQueue::ptr p_msgqueue = _p_qm->selectMsgQueue(queue_name);
            if (p_msgqueue == nullptr)
            {
                ELOG("队列【%s】不存在", queue_name.c_str());
                return false;
            }

            DeliveryMode mode = p_msgqueue->_durable ? DeliveryMode::DURABLE : DeliveryMode::UNDURABLE;

            // insert函数决定消失消息是否持久化优先考虑basic_props->delivery_mode(), 再考虑队列的持久化属性
            return _p_mm->insert(queue_name, basic_props, body, mode);
        }
        MessagePtr basicConsume(const std::string &queue_name)
        {
            return _p_mm->front(queue_name);
        }

        bool basicAck(const std::string &queue_name, const std::string &msg_id)
        {
            return _p_mm->ack(queue_name, msg_id);
        }

        void clear()
        {
            _p_bm->clear();
            _p_em->clear();
            _p_qm->clear();
            _p_mm->clear();
        }

    private:
        std::string _host_name;
        ExchangeManager::ptr _p_em;
        MsgQueueManager::ptr _p_qm;
        BindingManager::ptr _p_bm;
        MessageManager::ptr _p_mm;
    };
}
